
#include "excel.h"

#define instr_recs  instr_recs2
#define ext_instr_recs  ext_instr_recs2
#include "instr_db.h"
#include "instr_dat.h"

#undef OPER_TYPE_REC
#define OPER_TYPE_REC(x) L#x,
//
// If new oper type is to be defined, go to oper_type.h
//
LPTSTR operand_type_name[]= {
#include "oper_type_def.h"
L"unused"
} ;
#undef INSTR_REC
#define INSTR_REC(x) L#x,

LPTSTR instr_name[]= {
#include "instr_id_def.h"
L"unused"
};

#undef FUNIT_REC
#define FUNIT_REC(x) L#x,

LPTSTR funit_name[]={
#include "funit_def.h"
L"misc"
};

#undef OPER_FMT_REC
#define OPER_FMT_REC(x) L#x,

LPTSTR op_fmt_name[]={
#include "oper_fmt_def.h"
L"fmt_none"
};
int Export(CExcelUtil &util,LPWSTR wsTableName, struct instr_rec *record, DWORD dwNumRecord);
int Import(CExcelUtil &util,LPWSTR wsTableName, FILE *fp,LPWSTR var_name);
int Importx87(CExcelUtil &util,LPWSTR wsTableName, FILE *fp,LPWSTR var_name);


static LPWSTR op_format(OPERAND_TYPE op1,OPERAND_TYPE op2);

int instr_db_export()
{
	CExcelUtil ExcelUtil;
	if (ExcelUtil.OpenEx(L"D:\\project\\disasmx86\\x86-inst.xls"))
	{
		Export(ExcelUtil,L"simpleinst",instr_recs, sizeof (instr_recs)/sizeof (instr_recs[0]));
		Export(ExcelUtil,L"complexinst",ext_instr_recs, sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]));
		Export(ExcelUtil,L"x87inst",x87_instr_recs, sizeof (x87_instr_recs)/sizeof (x87_instr_recs[0]));
		Export(ExcelUtil,L"sseinst",instr_recs, sizeof (instr_recs)/sizeof (instr_recs[0]));
	}
	else
	{
		wprintf (L"Failed to open database.\n");
	}

	ExcelUtil.Close();
	return 0;
}
int instr_db_import()
{
	FILE *fp;
	CExcelUtil ExcelUtil;
	ExcelUtil.OpenEx(L"D:\\project\\disasmx86\\x86-inst.xls");

	fp = fopen("D:\\project\\disasmx86\\include\\instr_dat0.h","wt");
	if(fp)
	{
		fwprintf(fp,L"#ifndef __INSTR_H__\n"
			L"#define __INSTR_H__\n\n"
			L"\n\n"
			L"#include \"instr_db.h\"\n");

		Import(ExcelUtil,L"simpleinst",fp,L"instr_recs");
		Import(ExcelUtil,L"complexinst",fp,L"ext_instr_recs");
		Import(ExcelUtil,L"x87inst",fp,L"x87_instr_recs");

		fwprintf(fp,L"#endif    /*__INSTR_H__*/");
		fclose(fp);
	}
	ExcelUtil.Close();
	return 0;
}
int createflagxref()
{
	CExcelUtil ExcelUtil;
	ExcelUtil.OpenEx(L"\\x86-inst.xls");
	CString sSql;

	sSql.Format(
			L"CREATE TABLE FlagXRef"
			L"( OF TEXT,   SF TEXT,  ZF TEXT,  AF TEXT,   PF TEXT,  CF TEXT,TF TEXT,    IF TEXT,    DF TEXT,    NT TEXT,    RF TEXT, Instruction TEXT);"
			);
	try {
		ExcelUtil.ExecSql(sSql);
	} catch(CDBException *ex)
	{
		wprintf(L"%s",(LPCWSTR)ex->m_strError);
	}

	ExcelUtil.Close();
	return 0;
}

wchar_t * code_tmp( struct instr_rec rec );

WCHAR * mne_jcc[]={
	L"JO", L"JNO", L"JB", L"JNB", L"JE", L"JNE", L"JNA", L"JA", L"JS", L"JNS", L"JPE", L"JPO", L"JL", L"JNL", L"JNG", L"JG"

	};
int Export(CExcelUtil &util,LPWSTR wsTableName, struct instr_rec *record, DWORD dwNumRecord)
{
	CString sSql;

	sSql.Format(
			L"CREATE TABLE %s "
			L"(MNEM TEXT,code text,ID TEXT,ID2 TEXT,IDMASK TEXT,WMASK TEXT,SMASK TEXT,DMASK TEXT,OP1 TEXT,OP2 TEXT,DST TEXT,FMT TEXT, NAME TEXT, FUNIT TEXT,lockable text,repeatable text,pmodeonly text );",
			wsTableName);
	try {
		util.ExecSql(sSql);
	} catch(CDBException* ex)
	{
		wprintf(L"%s",(LPCWSTR)ex->m_strError);
	}

	try {
		for (DWORD i=0; i<dwNumRecord; i++) {
			WCHAR mnemonics[20];
			int j=0;

			char *s=record[i].mnemonics;

			while(*s) {mnemonics[j++]=*s++;}

			mnemonics[j]=0;

			sSql.Format(
				L"INSERT INTO %s "
				L"(MNEM, ID, ID2,IDMASK, WMASK, SMASK,DMASK,OP1,OP2,DST,FMT,NAME, FUNIT,lockable,repeatable,pmodeonly,code)"
				L"  VALUES('%s','0x%02X','0x%02X','0x%02X','%d','%d','%d','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s');",
				wsTableName,
				mnemonics,
				record[i].id,
				record[i].id2,
				record[i].mask,
				record[i].w_mask,
				record[i].sext_mask,
				record[i].dir_mask,
				operand_type_name[record[i].src1],
				operand_type_name[record[i].src2],
				operand_type_name[record[i].dst],
				op_fmt_name[record[i].op_fmt],//op_format(	record[i].src1,record[i].src2),
				instr_name[record[i].index],
				funit_name[record[i].funit],
				record[i].lockable ?L"true":L"false",
				record[i].repeatable ?L"true":L"false",
				record[i].pmodeonly ?L"true":L"false",
				code_tmp(record[i])//record[i].code
				);
			util.ExecSql(sSql);
		}
	}
	catch(CDBException* ex)
	{
       wprintf(L"%s",(LPCWSTR)ex->m_strError);
		return 0;
	}
	return 1;
}

int Import(CExcelUtil &util,LPWSTR wsTableName, FILE *fp,LPWSTR var_name)
{
	CString sSql;

	fwprintf (fp,L"struct instr_rec %s[] = {\n",var_name);

	try {

		sSql.Format(L"Select * from %s;",wsTableName);

		util.OpenRecordSet (sSql);
		while (!util.IsEOF())
		{
			CString id = util.GetFieldValue(L"ID"); 
			CString id2 = util.GetFieldValue(L"ID2");
			CString id_mask = util.GetFieldValue(L"IDMASK"); 
			CString w_mask = util.GetFieldValue(L"WMASK");
			CString sext_mask = util.GetFieldValue(L"SMASK");
			CString dir_mask =util. GetFieldValue(L"DMASK");
			CString op1 = util.GetFieldValue(L"OP1");
			CString op2 = util.GetFieldValue(L"OP2");
			CString fmt = util.GetFieldValue(L"FMT");

			CString dst = util.GetFieldValue(L"DST");
			CString mnemonics = util.GetFieldValue(L"MNEM");
			CString index = util.GetFieldValue(L"NAME");
			CString funit = util.GetFieldValue(L"FUNIT");
			CString lockable = util.GetFieldValue(L"lockable");
			CString repeatable = util.GetFieldValue(L"repeatable");
			CString pmodeonly = util.GetFieldValue(L"pmodeonly");
			CString code = util.GetFieldValue(L"code");
			util.NextRecord();
			fwprintf(fp,L"\t{\"%10s\", %5s, %5s, %5s, %5s, %5s, %5s, %8s, %8s, %8s, %8s, %8s,%8s , %8s,%8s,%8s,\"%s\"}%c\n", 
				mnemonics,
				id,
				id_mask,
				id2,
				w_mask,
				dir_mask,
				sext_mask,
				
				op1,
				op2,
				dst,
				fmt,
				
				index,
				funit,
				lockable,
				repeatable,
				L"false",
				code,

				util.IsEOF() ? L' ':L',');

		}
	}
	catch(CDBException* ex)
	{
        wprintf(L"%s",(LPCWSTR)ex->m_strError);
		return 0;
	}
	fwprintf (fp,L"};\n\n");
	return 1;
}


#define CF 1
#define AF 2
#define PF 4
#define ZF 8
#define SF 16
#define OF 32

unsigned char flags_str_to_hex(const char * str)
{
	unsigned char flag = 0;
	while (*str)
	{
		switch (*str)
		{
		case 'o': case 'O':flag |= OF;break;
		case 's': case 'S':flag |= SF;break;
		case 'z': case 'Z':flag |= ZF;break;
		case 'p': case 'P':flag |= PF;break;
		case 'a': case 'A':flag |= AF;break;
		case 'c': case 'C':flag |= CF;break;
		}
	}
	return flag;
}

void flags_bin_to_str( unsigned char flag, char str[7])
{
	str[6]=0;
	str[5] = (flag&CF) ? 'c' :'-';
	str[4] = (flag&AF) ? 'a' :'-';
	str[3] = (flag&PF) ? 'p' :'-';
	str[2] = (flag&ZF) ? 'z' :'-';
	str[1] = (flag&SF) ? 's' :'-';
	str[0] = (flag&OF) ? 'o' :'-';
}


static  LPWSTR  op_format(OPERAND_TYPE op1,OPERAND_TYPE op2)
{
LPWSTR s=L"fmt_none";

switch (op1)
{
case imp_hacc   :
case imp_dacc   :
case dontcare   :

case none      :
case imp_al     :
case imp_ah     :

case imp_ax     :
case imp_acc    :

	break;	

case ds_si:
	if(op2==es_di) s=L"XvYv";
	break;

case es_di:
	if(op2==reg_dx) s=L"YvDX";
	else if(op2==acc) s=L"Yvacc";
	break;

//
// misc types
//

case fs_gs     : 
   	s=L"FSGS";
	break;
case reg_dx  :  
	if(op2==acc) s=L"dx_acc";
	else if(op2==ds_si) s=L"DXXv";
	break;

case const_3 : 
   	s=L"int3";
	break;
case sreg    : //push/pop sreg only
   	s=L"SREG";
	break;
case reg     :
	switch(op2){
	case imm:s=L"regIv";
		break;
	case rmf:s=L"GvMp";
		break;
	case rm_tr     : 
		s=L"RdTd";
		break;
	case rm_cr     :
		s=L"RdCd";
		break;
	case rm_dr     : 
		s=L"RdDd";
		break;
	default:
   		s=L"REG";        //dec/inc/push/pop reg
	break;
	}
	break;
case acc     : 
	if(op2==imm_8) s=L"accIb";
	else if(op2==imm) s=L"accIv";
	else if(op2==reg_dx) s=L"acc_dx";
	else if(op2==ds_si) s=L"accXv";
	break;
//
// rm types
//

case rm2      : 
	s=L"EvGvIv";
	break;

case rm1      :  

	if(op2==const_1) s=L"Ev1";
	else
	if(op2==imm) s=L"EvIb";
	else
	if(op2==imm) s=L"EvIv";
	else
	if(op2==reg_cl) s=L"EvCL";
	else
	s=L"EvGv";
	break;

case rm8      : 
	s=L"Eb";
	break;
case rm_r16   :  
case rm16     :  
	s=L"Ew";
	break;
case rmf      :  
    s=L"Ep";
	break;
//
// reg field of modrmreg
//
case rm_tr     : 
	s=L"TdRd";
case rm_cr     :
	s=L"CdRd";
	break;
case rm_dr     : 
	s=L"DdRd";
	break;

case rm_sreg   : 
	s=L"SwEw";
	break;

//
// imm types
//




case imm_8     :
if(op2==acc) s=L"Ibacc";
	else s=L"Ib";//int
	break;
break;
case rel_8     : 
	s=L"Jb";
	break;
case imm_16    :
	if(op2==imm_8) s=L"IwIb";//enter 0,0
	else s=L"Iw";//retf 
	break;
case rel_16    :
case rel       :
	s=L"Jv";
	break;

case imm       : 

	break;
case imm_far   : 
	s=L"Ap";
	break;
case mem_off   : 
	s=L"Ov";
	break;
}
return s;
}



wchar_t buff[100];

wchar_t * code_tmp( struct instr_rec rec )
{
	wsprintf( buff ,L"%s.%s<(",funit_name[rec.funit],
			instr_name[rec.index]);
				;

	if (rec.src1!=none ) 
	wcscat ( buff,L" $0");
	if (rec.src2!=none ) 
	wcscat ( buff,L" ,$1");

	if (rec.funit==alu )
		wcscat ( buff,L" ,F");

	wcscat ( buff,L")>(");
	if (rec.dst==op1)
	wcscat ( buff,L" $0");
	else if (rec.dst!=none && rec.dst!=dontcare)
	wcscat ( buff,operand_type_name[rec.dst]);
	if (rec.funit==alu )
		wcscat ( buff,L" ,F");

	wcscat ( buff,L");");

	return buff;




}